/*******************************************************************************
 * Copyright (c) 2012, 2013 XML-Print Project.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     XML-Print Project - initial API and implementation
 ******************************************************************************/
package info.xmlprint.ui.mapping;

import info.xmlprint.core.format.Format;
import info.xmlprint.core.format.FormatGroup;
import info.xmlprint.core.mapping.ElementPath;
import info.xmlprint.core.mapping.ElementPathNode;
import info.xmlprint.core.mapping.Mapping;
import info.xmlprint.core.mapping.MappingGroup;
import info.xmlprint.core.project.PrintProject;
import info.xmlprint.core.xml.PAttribut;
import info.xmlprint.core.xml.PElement;
import info.xmlprint.core.xml.PElementGroup;
import info.xmlprint.core.xml.XMLScanner;
import info.xmlprint.run.Constants;
import info.xmlprint.run.RuntimeUtil;
import info.xmlprint.ui.message.GuiMessages;
import info.xmlprint.ui.widgets.IObserverControl;
import info.xmlprint.ui.widgets.ISubjectControl;
import info.xmlprint.util.FileUtil;
import info.xmlprint.util.ResizeColumns;
import info.xmlprint.util.XmlUtil;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.jaxen.JaxenException;
import org.jaxen.SimpleNamespaceContext;
import org.jaxen.dom4j.Dom4jXPath;

public class MappingSetup implements ISubjectControl {

	public static MappingSetup getInstance() {
		if (mappingSetup == null) {
			synchronized (MappingSetup.class) {
				if (mappingSetup == null) {
					mappingSetup = new MappingSetup();
				}
			}
		}
		return mappingSetup;
	}

	private Logger logger = Logger.getLogger(this.getClass().getName());

	private Mapping mapping;
	private Image rightImg = new Image(null, this.getClass()
			.getResourceAsStream(Constants.RIGHT_IMG));

	private Image elementImg = new Image(null, this.getClass()
			.getResourceAsStream(Constants.XML_ELEMENT_IMG));

	private FormatGroup formatGroup;
	private MappingGroup mappingGroup;
	private PElementGroup pElementGroup;
	private XMLScanner xmlScanner;

	// controls
	private static MappingSetup mappingSetup;
	private Shell shell;
	private Text xpathText, styleName;
	private Button xpathRadio, listRadio;
	private Composite xpathComp, positionComp, elementsComp, attrValComp;
	private Table elementsTable;
	private TreeViewer positionTreeViewer, attrValTreeViewer;
	private Combo typeCombo, formatCombo;

	private byte[] styleByteBak;
	private HashMap<TableItem, ElementPath> ePathHashMap;

	private List<IObserverControl> observerList = new ArrayList<IObserverControl>();

	private MappingSetup() {
		createControls();
	}

	public void createControls() {
		shell = new Shell(Display.getCurrent(), SWT.SHEET);
		shell.setLayout(new FillLayout());
		shell.setText(GuiMessages.Stileditor_Gui_Mapping);
		shell.addListener(SWT.Close, new Listener() {
			@Override
			public void handleEvent(Event event) {
				shell.setVisible(false);
				event.doit = false;
			}
		});
		ScrolledComposite sc = new ScrolledComposite(shell, SWT.H_SCROLL
				| SWT.V_SCROLL);

		Composite mainComp = new Composite(sc, SWT.NONE);
		mainComp.setLayout(new GridLayout(1, false));

		// Radio xPath
		xpathRadio = new Button(mainComp, SWT.RADIO);

		xpathComp = new Composite(mainComp, SWT.BORDER);

		listRadio = new Button(mainComp, SWT.RADIO);

		// elementsComp
		elementsComp = new Composite(mainComp, SWT.BORDER);
		{
			GridData gd = new GridData(GridData.FILL_BOTH);
			Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
			int maxHeight = d.height - 300;
			gd.heightHint = maxHeight > 500 ? 500 : maxHeight;
			elementsComp.setLayoutData(gd);
		}
		elementsComp.setLayout(new GridLayout());

		final SashForm elementsSashForm = new SashForm(elementsComp, SWT.BORDER);

		Composite elementsTypeComp = new Composite(elementsComp, SWT.NONE);
		elementsTypeComp.setLayout(new GridLayout(3, false));

		// TypeCombo
		new Label(elementsTypeComp, SWT.NONE)
				.setText(GuiMessages.Stileditor_Gui_SelectedElements + ":");
		typeCombo = new Combo(elementsTypeComp, SWT.NONE);
		typeCombo.setLayoutData(createGridData(null, 200, null));

		// Format
		Composite formatComp = new Composite(mainComp, SWT.BORDER);

		// Foot
		Composite footComp = new Composite(mainComp, SWT.NONE);

		// set xPath Radio
		{
			xpathRadio.setText(GuiMessages.Stileditor_Gui_XPath);
			xpathRadio.setLayoutData(new GridData());
			xpathRadio.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					setChildrenVisible(xpathComp, true);
					setChildrenVisible(elementsComp, false);
				}
			});
		}

		// set xpathComp
		{
			xpathComp.setLayoutData(createGridData(GridData.FILL_HORIZONTAL,
					null, null));
			xpathComp.setLayout(new GridLayout(5, false));

			new Label(xpathComp, SWT.NONE)
					.setText(GuiMessages.Stileditor_Gui_XPath + ": ");

			xpathText = new Text(xpathComp, SWT.NONE);
			xpathText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
			xpathText.addListener(SWT.KeyDown, new Listener() {
				public void handleEvent(Event e) { // damit "Return" auch
					// funktioniert
					if (e.keyCode == SWT.CR)
						xpathTest(xpathText.getText());
				}
			});

			Button testButton = new Button(xpathComp, SWT.NONE);
			testButton.setText("" + GuiMessages.Stileditor_Gui_Check + "");
			testButton.addListener(SWT.Selection, new Listener() {
				public void handleEvent(Event e) {
					xpathTest(xpathText.getText());
				}
			});
			/*
			 * Button xpathversion1 = new Button(xpathComp, SWT.RADIO);
			 * xpathversion1.setText(" 1.0 "); Button xpathversion2 = new
			 * Button(xpathComp, SWT.RADIO); xpathversion2.setText(" 2.0 ");
			 */
		}

		// set Elements Radio
		{
			listRadio.setText(GuiMessages.Stileditor_Gui_SelectFromList);
			listRadio.setLayoutData(new GridData());
			listRadio.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					setChildrenVisible(xpathComp, false);
					setChildrenVisible(elementsComp, true);
				}
			});
		}

		// set elementsSashForm
		{
			{
				GridData gd = new GridData(GridData.FILL_BOTH);
				gd.minimumWidth = 700;
				elementsSashForm.setLayoutData(gd);

			}

			// Links
			elementsTable = new Table(elementsSashForm, SWT.FULL_SELECTION
					| SWT.CHECK);

			// Mitte
			positionComp = new Composite(elementsSashForm, SWT.BORDER);
			positionComp.setLayout(new GridLayout(1, false));

			new Label(positionComp, SWT.NONE)
					.setText(GuiMessages.Stileditor_Gui_Position + ":");
			Composite positionTreeComp = new Composite(positionComp, SWT.NONE);
			positionTreeComp.setLayoutData(createGridData(GridData.FILL_BOTH,
					null, null));
			positionTreeComp.setLayout(new FillLayout());

			positionTreeViewer = new TreeViewer(positionTreeComp, SWT.NONE);

			positionComp.addControlListener(new ResizeColumns(positionTreeComp,
					positionTreeViewer.getTree()));

			// Rechts
			attrValComp = new Composite(elementsSashForm, SWT.BORDER);
			attrValComp.setLayout(new FillLayout());

			attrValTreeViewer = new TreeViewer(attrValComp, SWT.CHECK);

			// set elementTable
			{
				elementsTable.setHeaderVisible(true);

				TableColumn tc = new TableColumn(elementsTable, SWT.NONE);
				tc.setText(GuiMessages.Stileditor_Gui_Elements);
				tc.setWidth(200);

				// Column add Sorter
				// new TableColumnSortor().addStringSorter(elementsTable,
				// elementsTable.getColumn(0));

				elementsTable.addListener(SWT.Selection, new Listener() {
					public void handleEvent(Event e) {
						if (e.detail == SWT.CHECK) {
							elementsTable.setSelection((TableItem) e.item);
						}

						if (elementsTable.getSelection().length > 0) {
							TableItem ti = elementsTable.getSelection()[0];
							ElementPath ePath;
							if (ePathHashMap.get(ti) == null) {
								ePath = new ElementPath();
								PElement pe = new PElement(ti.getText());
								ElementPathNode epn = new ElementPathNode(pe);
								ePath.addNode(null, epn);
								ePath.setcurrPathNode(epn);
								ePathHashMap.put(ti, ePath);
							} else
								ePath = ePathHashMap.get(ti);

							positionTreeViewer.setInput(ePath);
							positionTreeViewer.refresh();
							positionTreeViewer.expandAll();

							setTypeCombo(ePath);

							setPositionTreeViewerSelected(ePath,
									positionTreeViewer, attrValTreeViewer);

						}

					}
				});
			}

			// set positionComp
			{
				setPositionTreeViewer(positionTreeComp, positionTreeViewer,
						attrValTreeViewer, typeCombo);
			}
			{
				setAttrValTreeViewer(attrValComp, attrValTreeViewer);
			}

			elementsSashForm.setWeights(new int[] { 2, 4, 3 });

			// set formatComp

			{
				formatComp
						.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
				formatComp.setLayout(new GridLayout(5, false));
				new Label(formatComp, SWT.NONE)
						.setText(GuiMessages.Stileditor_Gui_Description + ": ");
				styleName = new Text(formatComp, SWT.BORDER);
				styleName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

				new Label(formatComp, SWT.NONE)
						.setText(GuiMessages.Stileditor_Gui_SelectFormat + ": ");

				formatCombo = new Combo(formatComp, SWT.NONE);
				formatCombo.setLayoutData(new GridData());

			}

			// set footComp
			{

				footComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
				footComp.setLayout(new GridLayout(2, false));
				Button okButton = new Button(footComp, SWT.NONE);
				okButton.setText(GuiMessages.General_Gui_Okay);
				okButton.addListener(SWT.Selection, new Listener() {
					public void handleEvent(Event e) {
						//
						String error_no_xpathText = GuiMessages.Stileditor_Error_InvalidXPath;
						String error_no_name = GuiMessages.Stileditor_Error_EmptyDescription;
						String error_no_check = GuiMessages.Stileditor_Error_NoItemSelected;

						// fehlender XPath-Ausdruck
						if (xpathRadio.getSelection()
								&& (xpathText.getText() == null || xpathText
										.getText().trim().equals(""))) {
							MessageDialog.openInformation(null,
									GuiMessages.Stileditor_Info_Info,
									error_no_xpathText);
							return;
						}

						boolean isNew = mapping.getName() == null ? true
								: false;
						String mappingName = styleName.getText();
						Mapping _mapping = mappingGroup
								.getMappingByName(mappingName);
						if (_mapping != null && !_mapping.equals(mapping)) {
							MessageDialog
									.openInformation(
											null,
											GuiMessages.Stileditor_Info_Info,
											GuiMessages.Stileditor_Error_NameForMappingAlreadyUsed);
							return;
						}

						// mapping speichern
						if (xpathText.isEnabled())
							mapping.setSelect("0");
						else
							mapping.setSelect("1");

						mapping.setxPath(xpathText.getText());

						mapping.removeAll();
						boolean isChecked = false;
						for (TableItem ti : elementsTable.getItems()) {
							if (ti.getChecked()) {
								isChecked = true;
								ElementPath ep = ePathHashMap.get(ti);
								if (!mapping.contains(ep))
									mapping.addElementPath(ep);
							}
						}

						// wenn list ausgwaehlt aber checkbox nicht gekreuzt
						if (!isChecked && !xpathText.isEnabled()) {
							MessageDialog.openInformation(null,
									GuiMessages.Stileditor_Info_Info,
									error_no_check);
							return;
						}

						// ohne stylename
						if (styleName.getText().equals("")) {
							MessageDialog.openInformation(null,
									GuiMessages.Stileditor_Info_Info,
									error_no_name);
							return;
						}

						mapping.setName(mappingName);

						int i = formatCombo.getSelectionIndex();
						if (i >= 0) {
							// mapping.setFormatName(formatCombo.getItem(i));
							Format f = formatGroup.getFormatByName(formatCombo
									.getItem(i));
							mapping.setFormat(f);
						}

						if (isNew) {
							mappingGroup.getList().add(mapping);
						}
						notifyObservers();
						shell.close();
					}
				});

				Button cancelButton = new Button(footComp, SWT.NONE);
				cancelButton.setText(GuiMessages.General_Gui_Cancel);
				cancelButton.addListener(SWT.Selection, new Listener() {
					public void handleEvent(Event e) {
						InputStream in = new ByteArrayInputStream(styleByteBak);
						ObjectInputStream objectIn = null;

						try {
							objectIn = new ObjectInputStream(in);
						} catch (IOException e1) {
							logger.error("", e1);
							e1.printStackTrace();
						}
						try {
							int i = 0;

							for (Mapping es : mappingGroup.getList()) {
								if (es.equals(mapping)) {
									mappingGroup.getList().remove(mapping);
									mappingGroup.getList().add(i,
											(Mapping) objectIn.readObject());
									break;
								}
								i++;
							}

							in.close();

							notifyObservers();

						} catch (IOException e1) {
							logger.error("", e1);
							e1.printStackTrace();
						} catch (ClassNotFoundException e1) {
							logger.error("", e1);
							e1.printStackTrace();
						}
						shell.close();
					}
				});

			}
		}

		sc.setExpandHorizontal(true);
		sc.setExpandVertical(true);
		sc.setContent(mainComp);
		shell.pack();
		sc.setMinSize(mainComp.getSize());
		FileUtil.shellSetCenter(shell);
	}

	private GridData createGridData(Integer x, Integer w, Integer h) {
		GridData gridData = null;
		if (x != null)
			gridData = new GridData(x);
		else
			gridData = new GridData();

		if (w != null)
			gridData.widthHint = w;
		if (h != null)
			gridData.heightHint = h;

		return gridData;
	}

	@SuppressWarnings("unchecked")
	private List<Element> getDocNodes(String xPathStr, Object doc,
			SimpleNamespaceContext nsMap) {
		Dom4jXPath xPath = null;
		try {
			xPath = new Dom4jXPath(xPathStr);
		} catch (JaxenException e1) {
			e1.printStackTrace();
			MessageDialog.openError(null, GuiMessages.Stileditor_Error_Error,
					GuiMessages.Stileditor_Error_XPathError);
		}

		xPath.setNamespaceContext(nsMap);

		List<Element> list = null;
		try {
			list = xPath.selectNodes(doc);
		} catch (JaxenException e1) {
			e1.printStackTrace();
			MessageDialog.openError(null, GuiMessages.Stileditor_Error_Error,
					GuiMessages.Stileditor_Error_XPathError);

		}
		return list;
	}

	@Override
	public void notifyObservers() {
		for (IObserverControl o : observerList) {
			o.updateControl();
		}
	}

	public void open() {
		resetControls();

		ePathHashMap = new HashMap<TableItem, ElementPath>();
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			ObjectOutputStream objectout = new ObjectOutputStream(out);
			objectout.writeObject(mapping);
			objectout.flush();
		} catch (IOException e1) {
			logger.error("", e1);
			e1.printStackTrace();
		}
		styleByteBak = out.toByteArray();
		try {
			out.close();
		} catch (IOException e2) {
			logger.error("", e2);
			e2.printStackTrace();
		}

		for (String s : formatGroup.getFormatNames()) {
			formatCombo.add(s);
		}
		

		for (PElement pe : pElementGroup.getElements()) {
			TableItem ti = new TableItem(elementsTable, SWT.NONE);
			ti.setText(pe.getName());
			ti.setImage(elementImg);
		}

		// currElementsStyle ausfuellen
		if (mapping.getName() != null) {
			String _xpathText = mapping.getxPath();
			// wenn xpath

			if (_xpathText != null && !_xpathText.equals("")) {
				xpathText.setText(_xpathText);
			}

			// wenn aus Liste
			{
				for (ElementPath ep : mapping.getElementPaths()) {
					String elemName = ep.getCurrPathNode().getPElement()
							.getName();
					for (TableItem ti : elementsTable.getItems()) {
						if (ti.getText().equals(elemName)) {
							ti.setChecked(true);
							ePathHashMap.put(ti, ep);
						}
					}
				}

				// erste ElementPath automatisch aufklappen
				int index = 0;
				for (TableItem ti : elementsTable.getItems()) {
					if (ti.getChecked()) {
						elementsTable.select(index);
						ElementPath ePath = ePathHashMap.get(ti);
						positionTreeViewer.setInput(ePath);
						positionTreeViewer.refresh();
						positionTreeViewer.expandAll();

						setTypeCombo(ePath);

						attrValTreeViewer.setInput(null);
						attrValTreeViewer.refresh();
						setPositionTreeViewerSelected(ePath,
								positionTreeViewer, attrValTreeViewer);
						break;
					}
					index++;
				}

			}
			styleName.setText(mapping.getName());

			// MS Einstellung der aktuellen Auswahl funktioniert nicht
			int index = 0;
			for (String s : formatCombo.getItems()) {
				// System.out.println(s + mapping.getFormatName());
				if (mapping.getFormatName().equals(s)) {
					formatCombo.select(index);
					break;
				}
				index++;
			}

			//

		}

		if (mapping.getSelect().equals("0")) {
			xpathRadio.setSelection(true);
			setChildrenVisible(xpathComp, true);
			listRadio.setSelection(false);
			setChildrenVisible(elementsComp, false);

		} else {
			xpathRadio.setSelection(false);
			setChildrenVisible(xpathComp, false);
			listRadio.setSelection(true);
			setChildrenVisible(elementsComp, true);

		}
		formatCombo.getParent().layout();//fixed problem that width of formatCombo too small
		// formatCombo.redraw();
		// elementsTable.redraw();
		// positionTreeViewer.refresh();
		shell.open();

	}

	@Override
	public void registerObserver(IObserverControl observer) {
		if (!observerList.contains(observer)) {
			observerList.add(observer);
		}
	}

	@Override
	public void removeObserver(IObserverControl observer) {
		observerList.remove(observer);
	}

	private void resetControls() {
		formatCombo.removeAll();
		elementsTable.removeAll();
		xpathText.setText("");
		styleName.setText("");
		xpathRadio.setSelection(true);
		listRadio.setSelection(false);
	}

	private void setAttrValTreeViewer(Composite comp, final TreeViewer tv) {
		final Tree tree = tv.getTree();
		TreeColumn tc = new TreeColumn(tree, SWT.CENTER);
		tc.setWidth(200);

		// setContentProvider
		tv.setContentProvider(new ITreeContentProvider() {
			private ElementPathNode pn;

			private PElement pe;

			public void dispose() {
			}

			public Object[] getChildren(Object in) {
				if (in instanceof PAttribut) {
					PAttribut pa = (PAttribut) in;
					List<String> list = pa.getList();
					if (list != null && list.size() > 0)
						return list.toArray();
				}
				return null;
			}

			public Object[] getElements(Object in) {

				if (in instanceof ElementPathNode) {
					pn = (ElementPathNode) in;
					pe = pElementGroup.getElement(pn.getPElement().getName());

					PAttribut[] pa = pe.getAttributs();

					String s = "";
					for (PAttribut p : pa) {
						s += p.getName();
					}

					if (s.equals(""))
						return new Object[0];

					return pa;
				}

				return null;
			}

			public Object getParent(Object element) {
				return null;
			}

			public boolean hasChildren(Object in) {

				if (in instanceof PAttribut) {
					PAttribut pa = (PAttribut) in;
					if (pa.getName().equals(""))
						return false;

					List<String> list = pa.getList();
					if (list != null && list.size() > 0)
						return true;
				}
				return false;
			}

			public void inputChanged(Viewer viewer, Object oldInput,
					Object newInput) {
			}
		});

		// setLabelProvider
		tv.setLabelProvider(new ITableLabelProvider() {
			public void addListener(ILabelProviderListener listener) {
			}

			public void dispose() {
			}

			public Image getColumnImage(Object element, int columnIndex) {
				// if (element instanceof PAttribut) {
				// return attributImg;
				// }
				return null;
			}

			public String getColumnText(Object in, int columnIndex) {
				if (in instanceof PAttribut) {
					PAttribut pa = (PAttribut) in;
					if (pa.getName().equals(""))
						return "["
								+ GuiMessages.Stileditor_Gui_WithoutAttribute
								+ "]";

					return pa.getName();

				} else if (in instanceof String) {
					String s = (String) in;
					if (!s.equals(""))
						return "= \"" + s + "\"";
				}

				return null;
			}

			public boolean isLabelProperty(Object element, String property) {
				return false;
			}

			public void removeListener(ILabelProviderListener listener) {
			}
		});

		// tv.setInput(ePath);
		tv.expandAll();

		tv.getTree().addListener(SWT.Selection, new Listener() {

			@Override
			public void handleEvent(Event event) {
				if (event.detail == SWT.CHECK) {
					TreeItem currTi = (TreeItem) event.item;
					String currName = tiFilter(currTi.getText());

					ElementPathNode epn = (ElementPathNode) tv.getInput();

					// Attribut Node
					for (TreeItem t : currTi.getItems()) {
						if (currTi.getChecked()) {
							t.setChecked(true);
							epn.addAttribut(currName);
							epn.addValue(currName, tiFilter(t.getText()));

						} else {
							epn.removeAttribut(currName);
							t.setChecked(false);
						}
					}

					// Value Node
					if (currTi.getParentItem() != null) {
						TreeItem parentTi = currTi.getParentItem();
						String attrName = parentTi.getText();

						if (!currTi.getChecked()) {
							parentTi.setChecked(false);
							epn.removeValue(attrName, currName);
						} else {
							epn.addAttribut(attrName);
							epn.addValue(attrName, currName);

							// Wenn alle Value Node gekreuzt, wird Attrubut Node
							// gekreuzt.
							boolean allChildrenChecked = true;
							for (TreeItem t : parentTi.getItems()) {
								if (!t.getChecked()) {
									allChildrenChecked = false;// Wenn ein nicht
									// gekreuzt
									break;
								}
							}
							if (allChildrenChecked) {
								parentTi.setChecked(true);
							}
						}
					}
					// epn.toPrint();
				}

			}
		});
	}

	private void setAttrValTvChecked(TreeViewer tv, ElementPathNode epn) {

		Tree tree = tv.getTree();
		String attrName, val;
		boolean allChildrenChecked;

		for (TreeItem ti : tree.getItems()) {
			attrName = ti.getText();
			allChildrenChecked = true;

			for (TreeItem ti2 : ti.getItems()) {
				val = tiFilter(ti2.getText());
				// System.out.println("check:" + attrName + " " + val);
				if (epn.hasValue(attrName, val))
					ti2.setChecked(true);
				else
					allChildrenChecked = false;
			}
			if (allChildrenChecked)
				ti.setChecked(true);

		}

		// epn.toPrint();
	}

	private void setChildrenVisible(Composite comp, boolean b) {
		for (Control c1 : comp.getChildren()) {
			if (c1 instanceof Composite)
				setChildrenVisible((Composite) c1, b);

			c1.setEnabled(b);
		}
	}

	public void setInput(PrintProject pProject, Mapping mapping) {
		this.mapping = mapping;
 
		formatGroup = pProject.getFormatGroup();
		mappingGroup = pProject.getMappingGroup();
		pElementGroup = pProject.getPElementGroup();
		xmlScanner = pProject.getXMLScanner(false);
	}

	private void setPositionTreeViewer(Composite comp, final TreeViewer tv,
			final TreeViewer attrValTreeViewer, final Combo typeCombo) {

		final Tree tree = tv.getTree();
		tree.setLinesVisible(true);
		TreeColumn tc = new TreeColumn(tree, SWT.CENTER);
		tc.setText(GuiMessages.Stileditor_Gui_Elements);
		tc.setWidth(200);

		// setContentProvider
		tv.setContentProvider(new ITreeContentProvider() {
			public void dispose() {
			}

			public Object[] getChildren(Object parentElement) {
				if (parentElement instanceof ElementPathNode) {
					ElementPathNode pn = (ElementPathNode) parentElement;
					return pn.getChildrens();
				}
				return null;
			}

			public Object[] getElements(Object in) {
				if (in instanceof ElementPath) {
					ArrayList<ElementPathNode> list = new ArrayList<ElementPathNode>();
					ElementPath ef = (ElementPath) in;

					list.add(ef.getRoot());
					return list.toArray();
				}

				return null;
			}

			public Object getParent(Object element) {
				if (element instanceof ElementPathNode) {
					ElementPathNode pn = (ElementPathNode) element;
					return pn.getParent();
				}
				return null;
			}

			public boolean hasChildren(Object element) {
				if (element instanceof ElementPathNode) {
					ElementPathNode pn = (ElementPathNode) element;
					return pn.hasChildren();
				}
				return false;
			}

			public void inputChanged(Viewer viewer, Object oldInput,
					Object newInput) {
			}
		});

		// setLabelProvider
		tv.setLabelProvider(new ITableLabelProvider() {
			public void addListener(ILabelProviderListener listener) {
			}

			public void dispose() {
			}

			public Image getColumnImage(Object element, int columnIndex) {
				if (element instanceof ElementPathNode) {
					ElementPathNode pn = (ElementPathNode) element;
					if (pn.equals(pn.getInElementPath().getCurrPathNode()))
						return rightImg;
				}
				return null;
			}

			public String getColumnText(Object element, int columnIndex) {
				if (element instanceof ElementPathNode) {
					ElementPathNode pn = (ElementPathNode) element;
					return pn.getPElement().getName();
				}

				return null;
			}

			public boolean isLabelProperty(Object element, String property) {
				return false;
			}

			public void removeListener(ILabelProviderListener listener) {
			}
		});

		// tv.setInput(ePath);
		tv.expandAll();

		// wenn ein TreeNode klickt
		tree.addMouseListener(new MouseAdapter() {
			public void mouseDown(MouseEvent e) {

				TreeItem treeItem = tree.getItem(new Point(e.x, e.y));
				if (treeItem == null && e.button != 3) {
					tree.deselectAll();
					return;
				}

				IStructuredSelection selection = (IStructuredSelection) tv
						.getSelection();

				final ElementPathNode pn = (ElementPathNode) selection
						.getFirstElement();

				if (pn == null)
					return;

				// Attribute Werte anzeigen
				// createAttrValTree(pn, attrValComp, attrValTreeMap);
				String selectElementName = pn.getPElement().getName();

				if (e.button == 3) {
					Menu positionMenu = new Menu(shell, SWT.POP_UP);

					// Vater Element hinzufuegen.
					{
						MenuItem addParent = new MenuItem(positionMenu,
								SWT.CASCADE);
						Menu parentMenu = new Menu(shell, SWT.DROP_DOWN);
						addParent.setMenu(parentMenu);
						addParent.setText(" + "
								+ GuiMessages.Stileditor_Gui_ParentNode);
						// Wenn die Knoten ein Parent hat,dann ungueltig
						if (pn.getParent() != null)
							addParent.setEnabled(false);
						else {

							List<Element> allList = getDocNodes("//"
									+ selectElementName, xmlScanner.getXml(),
									xmlScanner.getSimpleNamespaceContext());

							// @SuppressWarnings("unchecked")
							// List<Element> allList = simpleXmlOfInput
							// .selectNodes("//" + selectElementName);

							Set<String> parentSet = new HashSet<String>();
							String childrenPath = "/"
									+ pn.getInElementPath()
											.getSimplePathString(false);
							for (Element ce : allList) {
								if (getDocNodes(childrenPath, ce,
										xmlScanner.getSimpleNamespaceContext())
										.size() > 0 && ce.getParent() != null)
									parentSet.add(ce.getParent().getName());

								/*
								 * if (ce.selectNodes(childrenPath).size() > 0
								 * && ce.getParent() != null)
								 * parentSet.add(ce.getParent().getName());
								 */
							}

							if (parentSet.size() > 0) {
								Iterator<String> parentIt = parentSet
										.iterator();
								while (parentIt.hasNext()) {
									final MenuItem mi = new MenuItem(
											parentMenu, SWT.PUSH);
									mi.setText(parentIt.next());
									mi.addListener(SWT.Selection,
											new Listener() {
												public void handleEvent(
														Event event) {
													pn.getInElementPath()
															.addNode(
																	new ElementPathNode(
																			new PElement(
																					mi.getText())),
																	pn);

													tv.refresh();
													tv.expandAll();
												}
											});
								}

							} else
								addParent.setEnabled(false);
						}
					}

					// Kinder Element hinzufuegen.
					{
						MenuItem addChildren = new MenuItem(positionMenu,
								SWT.CASCADE);
						Menu childrenMenu = new Menu(shell, SWT.DROP_DOWN);
						addChildren.setMenu(childrenMenu);
						addChildren.setText(" + "
								+ GuiMessages.Stileditor_Gui_ChildNode);
						// Wenn die Knode Kinder hat,dann ungueltig
						if (pn.hasChildren())
							addChildren.setEnabled(false);
						else {
							List<Element> childrenList = getDocNodes("//"
									+ pn.getInElementPath()
											.getSimplePathString(true) + "/*",
									xmlScanner.getXml(),
									xmlScanner.getSimpleNamespaceContext());
							/*
							 * @SuppressWarnings("unchecked") List<Element>
							 * childrenList = simpleXmlOfInput .getXml()
							 * .selectNodes( "//" + pn.getInElementPath()
							 * .getSimplePathString( true) + "/*");
							 */
							Set<String> childrenSet = new HashSet<String>();

							for (Element ce : childrenList) {
								childrenSet.add(ce.getName());
							}

							if (childrenSet.size() > 0) {
								Iterator<String> childrenIt = childrenSet
										.iterator();
								while (childrenIt.hasNext()) {
									{
										final MenuItem mc = new MenuItem(
												childrenMenu, SWT.PUSH);
										mc.setText(childrenIt.next());
										mc.addListener(SWT.Selection,
												new Listener() {
													public void handleEvent(
															Event event) {
														pn.getInElementPath()
																.addNode(
																		pn,
																		new ElementPathNode(
																				new PElement(
																						mc.getText())));
														tv.refresh();
														tv.expandAll();
													}
												});
									}
								}
							} else
								addChildren.setEnabled(false);
						}
					}

					// TreeNode entfernen
					MenuItem delItem = new MenuItem(positionMenu, SWT.PUSH);
					delItem.setText(GuiMessages.General_Gui_Delete);
					if (pn.equals(pn.getInElementPath().getCurrPathNode()))
						delItem.setEnabled(false);

					delItem.addListener(SWT.Selection, new Listener() {
						public void handleEvent(Event e) {
							pn.getInElementPath().removeNode(pn);
							tv.refresh();
							tv.expandAll();
						}
					});

					positionMenu.setVisible(true);

				} else {
					attrValTreeViewer.setInput(pn);

					attrValTreeViewer.refresh();
					attrValTreeViewer.expandAll();

					setAttrValTvChecked(attrValTreeViewer, pn);

				}
			}

		});

	}

	private void setPositionTreeViewerSelected(ElementPath ep, TreeViewer tv,
			TreeViewer attrValTreeViewer) {
		Tree tree = tv.getTree();
		ElementPathNode epn = ep.getCurrPathNode();

		for (TreeItem ti : tree.getItems()) {
			TreeItem currTi = TreeItemSearch(ti, epn);
			if (currTi != null) {
				tree.setSelection(currTi);
				attrValTreeViewer.setInput(epn);
				attrValTreeViewer.refresh();
				attrValTreeViewer.expandAll();
				setAttrValTvChecked(attrValTreeViewer, epn);
				return;
			}
		}
	}

	private void setTypeCombo(final ElementPath ep) {
		String eName = ep.getCurrPathNode().getPElement().getName();
		int elementType = ep.getElementType();
		typeCombo.removeAll();
		typeCombo.add(eName);
		typeCombo.add(GuiMessages.Stileditor_Gui_AllChildNodesOf + eName);
		typeCombo.add(GuiMessages.Stileditor_Gui_AllParentNodesOf + eName);

		if (elementType >= 0)
			typeCombo.select(elementType);
		else
			typeCombo.select(0);

		typeCombo.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				ep.setElementType(typeCombo.getSelectionIndex());
			}
		});

	}

	private String tiFilter(String s) {
		s = s.replaceAll("^= \"", "");
		s = s.replaceAll("\"$", "");
		return s;

	}

	/*
	 * 
	 */
	private TreeItem TreeItemSearch(TreeItem ti, ElementPathNode epn) {
		ElementPathNode curr = (ElementPathNode) ti.getData();

		if (curr.equals(epn)) {
			return ti;
		}

		for (TreeItem ti2 : ti.getItems()) {
			TreeItem currTi = TreeItemSearch(ti2, epn);
			if (currTi != null)
				return currTi;
		}
		return null;
	}

	private void xpathTest(String xPathStr) {
		if (xPathStr == null || xPathStr.trim().equals("")) {
			MessageDialog.openInformation(null,
					GuiMessages.Stileditor_Info_Info,
					GuiMessages.Stileditor_Error_InvalidXPath);
			return;
		}

		if (pElementGroup.noPrefixCount() > 1)
			MessageDialog.openWarning(null,
					GuiMessages.Stileditor_Warning_Warning,
					GuiMessages.Stileditor_Warning_Namespace_without_prefix);
		else if (pElementGroup.noPrefixCount() == 1) {
			xPathStr = XmlUtil.xPathAddPrefix(xPathStr,
					pElementGroup.getMainNamespacePrefix());

		}

		String s = GuiMessages.Stileditor_Gui_NumberOfMatches + ": ";
		Document doc = null;
		try {
			RuntimeUtil rt = RuntimeUtil.getInstance();

			PrintProject pProject = rt.getCurrentPrintProject();
			doc = DocumentHelper.parseText(rt.getContentText(pProject));
		} catch (DocumentException e) {
			logger.error("", e);
			e.printStackTrace();
		}

		SimpleNamespaceContext nsMap = new SimpleNamespaceContext(
				pElementGroup.getNamespaceMap());

		List<Element> list = getDocNodes(xPathStr, doc, nsMap);

		int i = list.size();
		if (i > 0) {
			MessageDialog.openInformation(null,
					GuiMessages.Stileditor_Info_Info, s + i);
		} else {
			MessageDialog.openInformation(null,
					GuiMessages.Stileditor_Info_Info,
					GuiMessages.Stileditor_Error_NoXPathResults);
		}

	}

}
